package com.zhuqi.aop;

import com.zhuqi.anno.LogPrint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author : ZhuQi
 * @version : 时间:2022/2/15 11:35 版本:
 */
@Aspect
public class LogAopPrint {

    private static final Logger log = LoggerFactory.getLogger(LogAopPrint.class);

    /**
     * 编辑织入点
     */
    @Pointcut("@annotation(com.zhuqi.anno.LogPrint)")
    public void logPointCut() {
    }

    /**
     * 前置通知 用于拦截操作
     *
     * @param proceedingJoinPoint 切点
     */
    @Around("logPointCut()")
    public Object aroundLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = handleLog(proceedingJoinPoint);
        return result;
    }


    /**
     * 日志输出
     *
     * @param proceedingJoinPoint
     */
    protected Object handleLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            Method method = getMethod(proceedingJoinPoint);
            // 获得注解
            LogPrint annotationLog = getAnnotationLog(method);
            // 操作
            if (ObjectUtils.isEmpty(annotationLog)) {
                throw new RuntimeException("注解为空");
            }
            // 方法名
            String methodName = method.getName();
            // 参数
            Object[] args = proceedingJoinPoint.getArgs();
            Object target = proceedingJoinPoint.getTarget();
            String simpleName = target.getClass().getSimpleName();
            log.info("类:" + simpleName + "-方法:" + methodName + "开始执行，参数为:" + Arrays.toString(args));
            long startTime = System.currentTimeMillis();
            Object result = proceedingJoinPoint.proceed();
            long endTime = System.currentTimeMillis();
            log.info("类:" + simpleName + "-方法:" + methodName + "开始结束，返回为:" + result);
            log.info("类:" + simpleName + "-方法:" + methodName + "耗时:" + (startTime - endTime) / 1000);
            return result;
    }

    /**
     * 拿到 连接点方法
     *
     * @param joinPoint 连接点
     * @return 方法
     */
    private Method getMethod(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        return methodSignature.getMethod();
    }


    /**
     * 是否存在注解，如果存在就获取并返回
     */
    private LogPrint getAnnotationLog(Method method) throws Exception {
        if (method != null) {
            return method.getAnnotation(LogPrint.class);
        }
        return null;
    }
}
